package com.lucenten.collect.utils;

import com.lucenten.collect.gnss.enums.FileSuffix;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.z.ZCompressorInputStream;

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipException;

@Slf4j
public class FileUtils {
    /**
     * 遍历并返回所有文件
     *
     * @param root
     * @return
     */
    public static List<String> getFileList(String root) {
        final List<String> fileList = new ArrayList<>();
        Path path = Paths.get(root);
        try {
            Files.walkFileTree(path, new SimpleFileVisitor<Path>(){
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    fileList.add(file.toAbsolutePath().toString());
                    return FileVisitResult.CONTINUE;
                }
                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    return FileVisitResult.CONTINUE;
                }
                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    return super.postVisitDirectory(dir, exc);
                }
            });
        } catch (IOException e) {
            log.error("");
        }

        return fileList;
    }

    /**
     * 创建目录
     *
     * @param path
     */
    public static void createDirs(Path path) {
        Path target = path;
        if (!Files.isDirectory(path)) {
            target = path.getParent();
        }
        if (Files.notExists(target)) {
            try{
                Files.createDirectories(target);
            }catch (IOException e) {
                log.error("文件夹创建失败："+e.toString(),e);
            }
        }
    }

    /**
     * 删除文件
     *
     * @param file
     * @return
     */
    public static boolean delete(Path file) {
        try {
            return Files.deleteIfExists(file);
        } catch (IOException e) {
            log.error("文件删除失败："+e.toString(),e);
        }
        return false;
    }

    /**
     * 文件复制
     *
     * @param source
     * @param target
     */
    public static boolean copy(Path source,Path target,boolean isReplace) {
        if (Files.notExists(source)) {
            log.debug("原始文件不存在");
            return false;
        }
        if (target == null) {
            log.debug("目标文件不存在");
            return false;
        }
        createDirs(target);
        try {
            Files.copy(source,target,isReplace ? StandardCopyOption.REPLACE_EXISTING : null);
            return true;
        } catch (IOException e) {
            log.error("文件复制失败："+e.toString(),e);
        }
        return false;
    }
    /**
     * 文件复制
     *
     * @param source
     * @param target
     */
    public static boolean copy(Path source,Path target) {
        return copy(source,target,true);
    }
    /**
     * 文件复制
     *
     * @param source
     * @param targets
     * @return
     */
    public static boolean copy(Path source,Path ...targets) {
        return copy(source,true,targets);
    }
    /**
     * 文件复制
     *
     * @param source
     * @param targets
     * @return
     */
    public static boolean copy(Path source,boolean isReplace,Path ...targets) {
        if (targets == null || targets.length <= 0) {
            return false;
        }
        for (Path target : targets) {
            copy(source,target,isReplace);
        }
        return true;
    }

    /**
     * 文件移动
     *
     * @param source
     * @param target
     * @return
     */
    public static boolean move(Path source,Path target, boolean isReplace) {
        if (Files.notExists(source)) {
            log.debug("原始文件不存在");
            return false;
        }
        if (target == null) {
            log.debug("目标文件不存在");
            return false;
        }
        createDirs(target);
        try {
            Files.move(source,target,isReplace ? StandardCopyOption.REPLACE_EXISTING : null);
            return true;
        } catch (IOException e) {
            log.error("文件移动失败："+e.toString(),e);
        }
        return false;
    }

    /**
     * 文件移动
     *
     * @param source
     * @param target
     * @return
     */
    public static boolean move(Path source,Path target) {
        return move(source, target, true);
    }

    /**
     * 获取文件后缀
     *
     * @param lowerName
     * @return
     */
    public static FileSuffix getFileSuffix(String lowerName) {
        // RNX格式是rnx.zip和.zip是重复的，所以必须先验证
        if (lowerName.endsWith(FileSuffix.RNX.getSuffix())){
            return FileSuffix.RNX;
        }
        for (FileSuffix suffix : FileSuffix.values()) {
            if (lowerName.endsWith(suffix.getSuffix())) {
               return suffix;
            }
        }
        return FileSuffix.OTHER;
    }

    /**
     * 执行解压
     * @param file
     * @return
     */
    public static void unZ(Path file, Path target) {
        FileUtils.createDirs(target);
        if (Files.exists(target)) {
            try {
                Files.delete(target);
            } catch (IOException e) {

            }
        }
        try (InputStream fin = Files.newInputStream(file); BufferedInputStream in = new BufferedInputStream(fin);
             ZCompressorInputStream zIn = new ZCompressorInputStream(in); OutputStream out = Files.newOutputStream(Files.createFile(target));
        ) {
            final byte[] buffer = new byte[2048];
            int n = 0;
            while (-1 != (n = zIn.read(buffer))) {
                out.write(buffer, 0, n);
            }
        } catch (Exception e) {
            log.error("文件解压失败"+e.toString(),e);
        }
    }

    /**
     * 执行解压
     * @param file
     * @return
     */
    public static void unGZ(Path file, Path target) {
        FileUtils.createDirs(target);
        if (Files.exists(target)) {
            try {
                Files.delete(target);
            } catch (IOException e) {

            }
        }
        try (InputStream fin = Files.newInputStream(file); BufferedInputStream in = new BufferedInputStream(fin);
             GzipCompressorInputStream zIn = new GzipCompressorInputStream(in); OutputStream out = Files.newOutputStream(Files.createFile(target));
        ) {
            final byte[] buffer = new byte[2048];
            int n = 0;
            while (-1 != (n = zIn.read(buffer))) {
                out.write(buffer, 0, n);
            }
        } catch (Exception e) {
            log.error("文件解压失败"+e.toString(),e);
        }
    }
}
